package com.harmontronics.hanma.paas.paas.domain.iam.service;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.harmontronics.hanma.paas.paas.consts.NumberEnum;
import com.harmontronics.hanma.paas.paas.domain.iam.entity.HmAction;
import com.harmontronics.hanma.paas.paas.domain.iam.entity.PermAction;
import com.harmontronics.hanma.paas.paas.domain.iam.entity.PermActionList;
import com.harmontronics.hanma.paas.paas.domain.iam.entity.RolePage;
import com.harmontronics.hanma.paas.paas.domain.iam.entity.RoleSingle;
import com.harmontronics.hanma.paas.paas.domain.iam.entity.valueobject.HmRoleFields;
import com.harmontronics.hanma.paas.paas.domain.iam.repository.po.HmRoleMenuPO;
import com.harmontronics.hanma.paas.paas.domain.organization.entity.valueobject.I18nKeyEnum;
import com.harmontronics.hanma.paas.paas.domain.iam.repository.persistence.HmRoleRepository;
import com.harmontronics.hanma.paas.paas.domain.iam.entity.HmRole;
import com.harmontronics.hanma.paas.paas.exception.ErrorKeyException;
import com.harmontronics.hanma.paas.paas.utils.MyBeanUtils;
import com.harmontronics.hanma.paas.paas.utils.StringUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.harmontronics.hanma.paas.paas.domain.iam.repository.mapper.HmRoleMapper;
import com.harmontronics.hanma.paas.paas.domain.iam.repository.po.HmRolePO;
import java.util.List;

@Service("hmRoleService")
@DS("#header.App-Unique")
public class HmRoleService{

    @Autowired
    private HmRoleRepository hmRoleRepository;

    @Autowired
    private HmRoleMapper hmRoleMapper;

    @Autowired
    private HmPermService hmPermService;

    @Autowired
    private HmRolePermService hmRolePermService;

    @Autowired
    private HmUserGroupRoleService hmUserGroupRoleService;

    @Autowired
    private HmRoleMenuService hmRoleMenuService;


    public HmRole findById( Long id){
            HmRolePO po =   hmRoleRepository.getById(id);
            List<Long> menuIdList = hmRoleMenuService.findByRoleId(id);
            HmRole hmRole = BeanUtil.toBean(po,HmRole.class);
            hmRole.setMenuIdList(menuIdList);
        return hmRole;
    }

    public Long createRoleAndPermission(RoleSingle roleCreate) {
        HmRole singleDto = roleCreate.getRole();
        if (singleDto == null) {
            throw new ErrorKeyException(I18nKeyEnum.CURRENT_ROLE_NOT_EXIST);
        }

        if (StringUtils.isEmpty(singleDto.getName())) {
            throw new ErrorKeyException(I18nKeyEnum.CURRENT_ROLE_NAME_NOT_EXIST);
        }

        validateField(0L, HmRoleFields.NAME, singleDto.getName());
        // 1.创建角色
        HmRolePO role = BeanUtil.toBean(roleCreate.getRole(), HmRolePO.class);
        role.setDeleted(NumberEnum.ZERO.getNum());
        hmRoleRepository.save(role);

        //写入角色菜单表
        List<Long> menuIdList = roleCreate.getMenuIdList();
        if(CollectionUtils.isNotEmpty(menuIdList)){
            hmRoleMenuService.insertToDb(role.getId(),menuIdList);
        }

        return role.getId();

        // 2.解析当前权限，写入数据库
        //hmRolePermService.insertRolePermAction(role.getId(), roleCreate.getPermissions());
    }

    public void updateRoleAndPermission(RoleSingle roleUpdate) {
        // 1.更新当前角色
        HmRolePO role = BeanUtil.toBean(roleUpdate.getRole(), HmRolePO.class);
        validateField(role.getId(), HmRoleFields.NAME, role.getName());
        hmRoleMapper.updateById(role);

        //2.更新角色菜单关系表
        List<Long> menuIdList = roleUpdate.getMenuIdList();
        hmRoleMenuService.deleteByRoleId(role.getId());
        if(CollectionUtils.isNotEmpty(menuIdList)){
            //先删除该角色之前的所有菜单
            hmRoleMenuService.insertToDb(role.getId(),menuIdList);
        }

        // 2.更新现有权限
        //hmRolePermService.updateRolePermAction(role.getId(), roleUpdate.getPermissions());
    }


    public void remove(List<Long> idList){
        hmRoleRepository.removeByIds(idList);
        //删除角色对应的菜单
        idList.forEach(id -> hmRoleMenuService.deleteByRoleId(id));
    }

    public RolePage selectRoleListWithNameAndStatus(
            Page<HmRolePO> pageable, String name, Integer status) {
        QueryWrapper<HmRolePO> roleQuery = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(name)) {
            roleQuery.like(HmRoleFields.NAME, name);
        }
        if (status != null) {
            roleQuery.eq(HmRoleFields.STATUS, status);
        }
        roleQuery
                .orderByDesc(HmRoleFields.ID);
        hmRoleMapper.selectPage(pageable, roleQuery);
        RolePage rolePage = new RolePage();
        rolePage.setData(MyBeanUtils.batchTransform(HmRole.class, pageable.getRecords()));
        rolePage.setPageNo(pageable.getCurrent());
        rolePage.setPageSize(pageable.getSize());
        rolePage.setTotalCount(pageable.getTotal());
        rolePage.setTotalPage(pageable.getPages());
        return rolePage;
    }

    public List<PermActionList> selectRolePermWithAppId(Long appId) {
        List<PermActionList> permActionList = hmPermService
                .selectAllPermAndAction(appId, NumberEnum.ONE.getNum());
        return permActionList;
    }

    public List<PermActionList> selectRolePermWithId(Long id) {
        HmRolePO role = hmRoleMapper.selectById(id);
        List<PermActionList> permActionList = hmPermService
                .selectAllPermAndAction(role.getAppId(), NumberEnum.ONE.getNum());
        List<PermActionList> rolePermActionList = hmRolePermService
                .selectCurrentPermAction(id);
        compareRolePermWithAllPerm(permActionList, rolePermActionList);
        return permActionList;
    }

    /**
     * 比较两者，对数据进行匹配
     *
     * @param permActionList 所有权限
     * @param rolePermActionList 当前角色的权限
     */
    private void compareRolePermWithAllPerm(List<PermActionList> permActionList,
            List<PermActionList> rolePermActionList) {
        for (PermActionList permActionListDto : permActionList) {
            for (PermActionList actionListDto : rolePermActionList) {
                // 当一级菜单相同时 比较二级菜单
                if (permActionListDto.getId().equals(actionListDto.getId())) {
                    compareSecondPerm(permActionListDto.getChildren(), actionListDto.getChildren());
                }
            }
        }
    }

    /**
     * 比较二级菜单
     */
    private void compareSecondPerm(List<PermAction> allPermAction,
            List<PermAction> rolePermAction) {
        for (PermAction allPerm : allPermAction) {
            for (PermAction rolePerm : rolePermAction) {
                if (allPerm.getId().equals(rolePerm.getId())) {
                    compareSecondPerm(allPerm.getChildren(), rolePerm.getChildren());
                    compareActions(allPerm.getActions(), rolePerm.getActions());
                }
            }
        }
    }

    /**
     * 对action操作进行比较 替换
     */
    private void compareActions(List<HmAction> allPermActions, List<HmAction> rolePermActions) {
        for (HmAction allPermAction : allPermActions) {
            for (HmAction rolePermAction : rolePermActions) {
                if (allPermAction.getId().equals(rolePermAction.getId())) {
                    allPermAction.setAccess(rolePermAction.getAccess());
                }
            }
        }
    }

    public void validateField(long id, String key, String value) {
        QueryWrapper<HmRolePO> wrapper = new QueryWrapper<>();
        wrapper.eq(key, value);
        //wrapper.eq(HmRoleFields.APP_ID, appId);

        //修改
        if (NumberEnum.ZERO.getNumLong() != id) {
            wrapper.ne(HmRoleFields.ID, id);
        }

        validateFieldImpl(wrapper);
    }

    private void validateFieldImpl(QueryWrapper<HmRolePO> wrapper) {
        List<HmRolePO> roleList = hmRoleMapper.selectList(wrapper);

        if (CollectionUtils.isNotEmpty(roleList)) {
            throw new ErrorKeyException(I18nKeyEnum.CURRENT_ROLE_EXIST);
        }
    }

    public void changeStatus(HmRole hmRole) {
        HmRolePO role = BeanUtil.toBean(hmRole, HmRolePO.class);
        hmRoleMapper.updateById(role);
    }

}